package com.hsgene.order.service.impl;

import com.hsgene.common.DeleteFlagType;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.common.util.result.NullObject;
import com.hsgene.common.util.validation.FieldChecker;
import com.hsgene.order.constants.v1.ActionType;
import com.hsgene.order.constants.v1.OrderPackageStatus;
import com.hsgene.order.domain.v1.GeneticTestingOrder;
import com.hsgene.order.domain.v1.GeneticTestingOrderAddtionA;
import com.hsgene.order.domain.v1.GeneticTestingOrderInterchange;
import com.hsgene.order.domain.v1.GeneticTestingOrderPackage;
import com.hsgene.order.exception.OrderErrorCode;
import com.hsgene.order.persistence.OrderInterchangeRepository;
import com.hsgene.order.persistence.OrderPackageRepository;
import com.hsgene.order.persistence.OrderRepository;
import com.hsgene.order.service.InternalOrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 内部API订单ServiceImpl
 *
 * @author wangbing
 * @version 1.0, 2018/10/9
 */
@Service
public class InternalOrderServiceImpl implements InternalOrderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(InternalOrderServiceImpl.class);

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private OrderInterchangeRepository orderInterchangeRepository;

    @Resource
    private OrderPackageRepository orderPackageRepository;

    @Override
    public ApiResult<GeneticTestingOrder> getTestingOrder(String orderId) {
        GeneticTestingOrder order = orderRepository.findById(orderId);
        if (order == null) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        return ApiResult.succ(order);
    }

    @Override
    public ApiResult<GeneticTestingOrderInterchange> getTestingOrderInterchange(String interchangeId) {
        GeneticTestingOrderInterchange interchange = orderRepository.findInterchangeById(interchangeId);
        if (interchange == null) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NOT_EXISTED);
        }
        return ApiResult.succ(interchange);
    }

    @Override
    public ApiResult<GeneticTestingOrderAddtionA> getTestingOrderAdditionA(String orderId) {
        GeneticTestingOrderAddtionA addtionA = orderRepository.findAddtionAByOrderId(orderId);
        if (addtionA == null) {
            return ApiResult.fail(OrderErrorCode.ORDER_ADDITION_A_NOT_EXISTED);
        }
        return ApiResult.succ(addtionA);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> payInterchangeCallBack(String interchangeId, BigDecimal amount) {
        FieldChecker.checkEmpty(interchangeId, "套餐变更记录id");
        FieldChecker.checkEmpty(amount, "支付金额");

        GeneticTestingOrderInterchange interchange = orderInterchangeRepository.findById(interchangeId);
        if (interchange == null || DeleteFlagType.DELETE.equals(DeleteFlagType.getEnum(interchange.getDeleteFlag()))) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NOT_EXISTED);
        }

        List<GeneticTestingOrderInterchange> interchanges = orderInterchangeRepository.queryByRecordNo(interchange.getRecordNo());
        GeneticTestingOrder order = orderRepository.findById(interchange.getNewOrderId());
        if (order == null || DeleteFlagType.DELETE.equals(DeleteFlagType.getEnum(order.getDeleteFlag()))) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        GeneticTestingOrderAddtionA addtionA = orderRepository.findAddtionAByOrderId(interchange.getNewOrderId());
        if (addtionA == null) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        if (!Integer.valueOf(0).equals(addtionA.getPackageChangeFlag())) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NONE_PERMISSION);
        }
        if (addtionA.getIsReplenishment() == null || Integer.valueOf(0).equals(addtionA.getIsReplenishment())) {
            LOGGER.warn("orderId={}不需要补款！", addtionA.getGeneticTestingOrderId());
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NONE_PERMISSION);
        }
        if (!amount.equals(addtionA.getReplenishmentAmount())) {
            LOGGER.error("InterchangeRecordNo={},回调时支付金额[{}]与实际补款金额[{}]不一致！", interchange.getRecordNo(), amount, interchange.getDifferenceBalance());
        }

        interchanges.forEach(e -> {
            if (e.getReplenishmentFlag() == 1 && e.getStatus() != 2) {
                if (e.getStatus() != 2) {
                    e.setStatus(2);
                    orderInterchangeRepository.update(e);
                    ActionType actionType = ActionType.getEnum(e.getActionType());
                    // 查询对应套餐变更信息
                    GeneticTestingOrderPackage newPackage = orderPackageRepository.findOrderPackage(e.getNewOrderId(), e.getNewPackageId());
                    if (!actionType.needSupplementAmount()) {
                        // 不需要补款的直接标记新套餐已确认
                        newPackage.setPackageConfirmFlag(1);
                        GeneticTestingOrderPackage oldPackage = orderPackageRepository.findOrderPackage(e.getNewOrderId(), e.getOldPackageId());
                        if (oldPackage != null) {
                            // 终止原有套餐，从变更待确认 -> 终止
                            oldPackage.setStatus(OrderPackageStatus.END.getCode());
                            orderPackageRepository.updateForInterchange(oldPackage);
                        }
                    }
                    newPackage.setPackageConfirmFlag(1);
                    newPackage.setSupplementStatus(2);
                    orderPackageRepository.updateForInterchange(newPackage);
                }
            }
        });
        addtionA.setUpdateDateTime(new Date());
        addtionA.setPackageChangeFlag(1);
        addtionA.setIsReplenishment(0);
        orderRepository.updateAdditionAForInterchange(addtionA);

        order.setTotalCharges(order.getTotalCharges().add(addtionA.getReplenishmentAmount()));
        order.setUpdateDateTime(new Date());
        orderRepository.updateOrderForInterchange(order);

        return ApiResult.succ();
    }
}
